package com.lagou.rocketmq.task.service.impl;

import com.alibaba.fastjson.JSON;
import com.lagou.rocketmq.task.constant.RedisKey;
import com.lagou.rocketmq.task.dao.ProductDao;
import com.lagou.rocketmq.task.enumration.OrderResponseCodeEnum;
import com.lagou.rocketmq.task.model.Response;
import com.lagou.rocketmq.task.model.dto.CreateOrderReq;
import com.lagou.rocketmq.task.model.entity.SeckillingProductDO;
import com.lagou.rocketmq.task.model.event.CreateOrderEvent;
import com.lagou.rocketmq.task.service.SeckillingService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;

import java.util.concurrent.TimeUnit;
import redis.clients.jedis.JedisPool;

@Service
public class SeckillingServiceImpl implements SeckillingService {

  private static final Logger logger = LoggerFactory.getLogger(SeckillingServiceImpl.class);

  @Autowired
  private RocketMQTemplate rocketMQTemplate;

  @Autowired
  private JedisPool jedisPool;

  @Autowired
  private ProductDao productDao;

  @Autowired
  private RedissonClient redissonClient;

  @Override
  public Response addOrder(CreateOrderReq req) {
    // 分布式锁加锁
    String seckillingLockKey = RedisKey.getSeckillingLock(req.getCustomerId(), req.getProductId());
    RLock lock = redissonClient.getLock(seckillingLockKey);
    try {
      if (lock.tryLock(1, TimeUnit.SECONDS.toSeconds(3), TimeUnit.SECONDS)) {
        // 校验库存
        Integer productInventory = getProductInventory(req.getProductId());
        if (productInventory <= 0) {
          return new Response(OrderResponseCodeEnum.OUT_OF_STOCK.getCode(), OrderResponseCodeEnum.OUT_OF_STOCK.getDesc());
        }

        // 发送下单事件
        CreateOrderEvent createOrderEvent = new CreateOrderEvent(req.getProductId(), req.getCustomerId());
        rocketMQTemplate.convertAndSend("seckilling_create_order", JSON.toJSONString(createOrderEvent));
        return new Response();
      }

    } catch (InterruptedException e) {
      logger.error("抢购获取分布式锁失败", e);
      return new Response(OrderResponseCodeEnum.SECKILLING_FAILURE.getCode(), OrderResponseCodeEnum.SECKILLING_FAILURE.getDesc());
    } finally {
      if (lock.isHeldByCurrentThread()) {
        lock.unlock();
      }
    }

    return new Response(OrderResponseCodeEnum.SECKILLING_FAILURE.getCode(), OrderResponseCodeEnum.SECKILLING_FAILURE.getDesc());
  }

  /**
   * 获取商品库存
   *
   * @param productId
   * @return
   */
  private Integer getProductInventory(Integer productId) {
    String productInventoryKey = RedisKey.getProductInventoryKey(productId);

    try (Jedis jedis = jedisPool.getResource()) {
      String value = jedis.get(productInventoryKey);
      if (StringUtils.isEmpty(value)) {
        SeckillingProductDO product = productDao.getOne(productId);
        value = product.getInventory().toString();
      }

      jedis.set(productInventoryKey, value);
      return Integer.parseInt(value);
    }
  }
}
